package com.smark.circularprodemo;

import android.animation.Keyframe;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;

import androidx.annotation.Nullable;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;


/**
 * Created by smark on 2020/3/19.
 * 邮箱：smarkwzp@163.com
 */
public class CircularProgressView extends View {
    private final float radius = dpToPixel(80);
    private RectF arcRectF = new RectF();
    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private float progress = 0;
    private int numSize = 45;
    private int duration = 1000;
    private int CircleStrokeWidth = 15;
    private int mBounceBackNum = 10;
    private ObjectAnimator animator;
    private int mCircleColor = Color.RED;
    private int mTextColor = Color.WHITE;
    private int[] colorArr = new int[]{Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW,
            Color.LTGRAY};
    private boolean isShader = false;
    private boolean isBounceBack = false;


    public CircularProgressView(Context context) {
        super(context);
    }

    public CircularProgressView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public CircularProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @SuppressWarnings("unused")
    public float getProgress() {
        return progress;
    }

    @SuppressWarnings("unused")
    public void setProgress(float progress) {
        this.progress = progress;
        invalidate();
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        float centerX = getWidth() / 2;
        float centerY = getHeight() / 2;


        //画进度
        paint.setStyle(Paint.Style.STROKE);
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setColor(mCircleColor);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeWidth(dpToPixel(CircleStrokeWidth));
        if (isShader) {
            Shader mShader = new LinearGradient(0, 0, 100, 100,
                    colorArr, null, Shader.TileMode.REPEAT); // 一个材质,打造出一个线性梯度沿著一条线。
            paint.setShader(mShader);
        }

        arcRectF.set(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
        canvas.drawArc(arcRectF, 90, progress * 3.6f, false, paint);

        paint.reset();
        paint.setTextSize(dpToPixel(numSize));
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setColor(mTextColor);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawText((int) progress + "%", centerX, centerY - (paint.ascent() + paint.descent()) / 2, paint);

    }


    /**
     * 设置进度
     *
     * @param progress
     */
    public void setCircleProgress(float progress) {
        this.progress = progress;
        if (!isBounceBack || this.progress + mBounceBackNum >= 100) {
            beginAnimator();
        } else {
            beginBounceBackAnimator();
        }

    }

    /**
     * 设置进度值字体大小
     *
     * @param size
     */
    public void setNumSize(int size) {
        this.numSize = size;
    }


    /**
     * 设置进度宽度
     *
     * @param width
     */
    public void setCircleStrokeWidth(int width) {
        this.CircleStrokeWidth = width;
    }


    /**
     * 设置动画时长
     *
     * @param duration
     */
    public void setAnimatorDuration(int duration) {
        this.duration = duration;
    }

    /**
     * 设置进度条颜色
     *
     * @param circleColor
     */
    public void setCircleColor(int circleColor) {
        this.mCircleColor = circleColor;
    }

    /**
     * 设置进度字体颜色
     *
     * @param textColor
     */
    public void setTextColor(int textColor) {
        this.mTextColor = textColor;
    }


    /**
     * 是否开启进度颜色渐变
     *
     * @param isShader
     */
    public void isOpenShader(boolean isShader) {
        this.isShader = isShader;
    }


    /**
     * 设置渐变颜色数组
     *
     * @param colorArr
     */
    public void setShaderColorArr(int[] colorArr) {
        isOpenShader(true);
        this.colorArr = colorArr;
    }


    /**
     * 是否开启回弹动画
     *
     * @param isBounceBack
     */
    public void isOpenBounceBack(boolean isBounceBack) {
        this.isBounceBack = isBounceBack;
    }

    /**
     * 设置回弹数值 回弹数值是基于进度来设置的，不宜过大，当进度为100时，不执行回弹效果
     *
     * @param bounceBackNum
     */
    public void setBounceBackNum(int bounceBackNum) {
        this.mBounceBackNum = bounceBackNum;

    }


    /**
     * 开始执行动画  普通动画
     */
    private void beginAnimator() {
        animator = ObjectAnimator.ofFloat(this, "progress", 0, progress);
        animator.setDuration(duration);
        animator.setInterpolator(new FastOutSlowInInterpolator());
        animator.start();
    }


    /**
     * 开始执行动画  回弹动画
     */
    private void beginBounceBackAnimator() {

        Keyframe keyframe1 = Keyframe.ofFloat(0, 0);
        Keyframe keyframe2 = Keyframe.ofFloat(0.5f, progress + mBounceBackNum);
        Keyframe keyframe3 = Keyframe.ofFloat(1, progress);
        PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("progress", keyframe1, keyframe2, keyframe3);
        animator = ObjectAnimator.ofPropertyValuesHolder(this, holder);
        animator.setDuration(duration);
        animator.setInterpolator(new FastOutSlowInInterpolator());
        animator.start();
    }


    /**
     * dp转px
     *
     * @param dp
     * @return
     */
    private float dpToPixel(float dp) {
        DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
        return dp * metrics.density;
    }
}
